package machineLearning;

import java.util.ArrayList;

import javax.management.modelmbean.XMLParseException;

import parser.RTEXmlParser;

import matching.Matcher;

import data.RTEData;
import data.RTEPreprocessedData;

import weka.classifiers.Classifier;
import weka.classifiers.Evaluation;
import weka.classifiers.bayes.NaiveBayes;
import weka.classifiers.lazy.IBk;
import weka.core.*;

public class Classification extends Matcher {

	public Classification(String task, double threshold) {
		super(task, threshold);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void match() {
		ArrayList<RTEPreprocessedData> preprocessedData = RTEPreprocessedData.rtePreprocessedDataList;
		ArrayList<RTEData> data = RTEData.RTEDataList;
		
		numberOfTextCases = RTEData.RTEDataList.size() * 1/3;
		
		Attribute wordMatch  = new Attribute("WordMatch");
		Attribute lemmaMatch = new Attribute("LemmaMatch");
		Attribute lemmaPosTagMatch = new Attribute("LemmaPosTagMatch");
		Attribute bigramMatch = new Attribute("BiGramMatch");
		
		FastVector entailmentValue = new FastVector();
		entailmentValue.addElement("yes");
		entailmentValue.addElement("no");
		
		Attribute classAttribute = new Attribute("entailment", entailmentValue);
		
		FastVector featureVector = new FastVector();
		featureVector.addElement(wordMatch);
		featureVector.addElement(lemmaMatch);
		featureVector.addElement(lemmaPosTagMatch);
		featureVector.addElement(bigramMatch);
		featureVector.addElement(classAttribute);
		
		int size = (int)Math.floor(data.size() * (float)2/3);
		Instances trainingSet = new Instances("training", featureVector, size);
		trainingSet.setClassIndex(4);
		
		for(int i = 0; i < size; i++) {
			Instance instance = new Instance(featureVector.size());
			instance.setValue((Attribute)featureVector.elementAt(0), data.get(i).getWordMatchPercentage());
			instance.setValue((Attribute)featureVector.elementAt(1), preprocessedData.get(i).getLemmaMatchPercentage());
			instance.setValue((Attribute)featureVector.elementAt(2), preprocessedData.get(i).getLemmaPosTagMatchPercentage());
			instance.setValue((Attribute)featureVector.elementAt(3), preprocessedData.get(i).getBiGramMatchPercentage());
			instance.setValue((Attribute)featureVector.elementAt(4), preprocessedData.get(i).isEntailment() ? "yes" : "no");
			trainingSet.add(instance);
		}
		Instances dataSet = new Instances("data", featureVector, size);
		dataSet.setClassIndex(4);
		
		
		for(int i = size; i < data.size(); i++) {
			Instance instance = new Instance(featureVector.size());
			instance.setValue((Attribute)featureVector.elementAt(0), data.get(i).getWordMatchPercentage());
			instance.setValue((Attribute)featureVector.elementAt(1), preprocessedData.get(i).getLemmaMatchPercentage());
			instance.setValue((Attribute)featureVector.elementAt(2), preprocessedData.get(i).getLemmaPosTagMatchPercentage());
			instance.setValue((Attribute)featureVector.elementAt(3), preprocessedData.get(i).getBiGramMatchPercentage());
			instance.setValue((Attribute)featureVector.elementAt(4), preprocessedData.get(i).isEntailment() ? "yes" : "no");
			
			dataSet.add(instance);
		}
		
		Classifier model = new IBk(11);
		try {
			model.buildClassifier(trainingSet);
			
			double pred;
			for(int i = 0; i < dataSet.numInstances(); i++) {
				pred = model.classifyInstance(dataSet.instance(i));
				
				String actual = dataSet.classAttribute().value((int)dataSet.instance(i).classValue());
				String predicted = dataSet.classAttribute().value((int)pred);
//				System.out.println(data.get(size + i).getId() + " - "+ actual + " -" + predicted);
				addJudgement(data.get(size + i).getId(), predicted == "yes" ? true : false);
				
				if(!actual.equals(predicted))
					errors.add(data.get(size + i).getId());
			}
			
			Evaluation testClassifier = new Evaluation(trainingSet);
			
			testClassifier.evaluateModel(model, dataSet);
			
			correctness = (float)(testClassifier.correct() / (data.size() - size));
			this.entailments = (int) testClassifier.correct();
			
			System.out.println("Training cases: " + size + ", test cases: " + (data.size() -size) + ", correct: " + testClassifier.correct() + ", failed: " + (data.size() - size - testClassifier.correct()));
			System.out.println(this);
			
			RTEXmlParser.WritePredictions("MachineLearning", getJudgementData());
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
